﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics.Contracts;

namespace YasharEl.Infrastructure.EntityModel
{
    /// <summary>
    /// The date time provider implements <see cref="IDateTimeProvider"/> to return date and time information.
    /// The date time provider can be used to abstract access to the <see cref="DateTime"/> class to support
    /// better testability by mocking e.g. <see cref="DateTime.Now"/>.
    /// </summary>
    public class DateTimeProvider : IDateTimeProvider
    {
        private readonly bool useUtc;
        private readonly string standartFormat;

        public bool IsUseUtc
        {
            get { return useUtc; }
        }

        public string StandartFormat
        {
            get { return standartFormat; }
        }

        public DateTimeProvider(bool useUtc, string standartFormat)
        {
            Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(standartFormat), "standartFormat could not be null or empty.");
            this.useUtc = useUtc;
            this.standartFormat = standartFormat;
        }

        /// <summary>
        /// Gets a <see cref="DateTime"/> representing actual date and time. Returns <see cref="DateTime.Now"/>
        /// </summary>
        public DateTime Now
        {
            get
            {
                if (IsUseUtc)
                    return DateTime.UtcNow;

                return DateTime.Now;
            }
        }

        /// <summary>
        /// Gets a <see cref="DateTime"/> representing today. Returns <see cref="DateTime.Today"/>
        /// </summary>
        public DateTime Today
        {
            get
            {
                if (IsUseUtc)
                    return DateTime.Today.ToUniversalTime();

                return DateTime.Today;
            }
        }


        public DateTime Parse(string dateTimeString)
        {
            try
            {
                return DateTime.ParseExact(dateTimeString, standartFormat, null);
            }
            catch (FormatException fe)
            {
                throw new DateTimeConvertException(dateTimeString, standartFormat, fe);
            }
            catch (Exception)
            {
                throw;
            }
        }

        public string Parse(DateTime date)
        {
            if (IsUseUtc)
                return date.ToUniversalTime().ToString(standartFormat);

            return date.ToString(standartFormat);
        }


        public DateTime CalibrateToCurrentSystem(DateTime notCalibratedValue)
        {
            if (IsUseUtc)
            {
                return notCalibratedValue.ToUniversalTime();
            }
            else
            {
                return notCalibratedValue.ToLocalTime();
            }
        }
    }
}
